package edu.gdpu.classloader;

import org.omg.PortableServer.RequestProcessingPolicyValue;

import java.io.*;

/**
 * @author mazebin
 * @date 2021年 07月08日 10:55:28
 */
public class CustomClassLoader extends ClassLoader {
    private String classLoaderName;
    private String path;
    private static final String filePost = ".class";

    public CustomClassLoader(ClassLoader parent) {
        super(parent);
    }
    public String getPath() {
        return path;
    }

    public void setPath(String path) {
        this.path = path;
    }

    public CustomClassLoader(ClassLoader parent, String classLoaderName) {
        super(parent);//将系统类加载器作为父加载器
        this.classLoaderName = classLoaderName;
    }

    public CustomClassLoader(String classLoaderName) {
        super();//将系统类加载器作为父类加载器
        this.classLoaderName = classLoaderName;
    }

    public CustomClassLoader() {
        super();
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {

        String fileName = getFileName(name);
        byte[] bytes =loadClassData(fileName);
        if(bytes == null){
            return null;
        }
        System.out.println("findClass,输出这句话说明我们自己的类加载器加载了指定的类");
        return defineClass(name,bytes,0,bytes.length);
    }
    private byte[] loadClassData(String name){
        byte[] data = null;

        try(InputStream input = new FileInputStream(new File(path+name+filePost));
            ByteArrayOutputStream output = new ByteArrayOutputStream();
        ) {
            int len =0;
            while (-1 !=(len = input.read())){
                output.write(len);


            }
            data = output.toByteArray();
            input.close();
            output.close();
        }catch ( Exception e ){
            e.printStackTrace();
        }

        return data;
    }
    private String getFileName(String className){
        int i = className.lastIndexOf(".");
        if( i== -1)
        {
            return className;
        }else{
            return className.substring(i+1,className.length());
        }

    }
    private static void  test1(CustomClassLoader classLoader) throws Exception{

        Class<?> aClass = classLoader.loadClass("edu.gdpu.classloader.ClassLoaderTest1");
        //这里由于双亲委派机制：类加载器在接受到某个加载类的请求时，会先将加载请求委派给它的父类加载器，他的父类加载器无法完成该请求，才会交由它自己去加载
        //所以这里建议把源码文件先删掉，不然idea会重新生成classes,还是会导致系统类加载器能够加载到这个类
        Object instance = aClass.newInstance();
        System.out.println(instance);
        System.out.println("ClassLoader:"+instance.getClass().getClassLoader());
    }

    public static void main(String[] args) throws Exception {
        CustomClassLoader customClassLoader = new CustomClassLoader("CustomClassLoader");
        customClassLoader.setPath("D:\\testClass\\");
        test1(customClassLoader);
        System.gc();
        Thread.sleep(10000);
        CustomClassLoader loader = new CustomClassLoader("");
        loader.setPath("D:\\testClass\\");
        test1(loader);
        /**
         * 输出结果：
         * findClass,输出这句话说明我们自己的类加载器加载了指定的类
         * edu.gdpu.classloader.ClassLoaderTest1@135fbaa4
         * ClassLoader:edu.gdpu.classloader.CustomClassLoader@7f31245a
         * findClass,输出这句话说明我们自己的类加载器加载了指定的类
         * edu.gdpu.classloader.ClassLoaderTest1@2503dbd3
         * ClassLoader:edu.gdpu.classloader.CustomClassLoader@45ee12a7
         */
    }

}
